package com.lu.security.cipher;

import android.text.TextUtils;

import org.jetbrains.annotations.NotNull;

import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

import javax.crypto.Cipher;

import com.lu.security.key.DefaultKey;
import com.lu.security.key.KeyReader;
import com.lu.security.log.SecurityLog;
import com.lu.security.tools.HexTools;

/**
 * author: luqihua
 * date:2019-07-10
 * description: RSA
 **/
public class RSACipher {
    private static final String TAG = "RJCipher";

    private static final String RSA_MODEL = "RSA/ECB/PKCS1Padding";

    @NotNull
    private final PrivateKey mPrivateKey;

    @NotNull
    private final PublicKey mPublicKey;

    public static RSACipher getDefault() {
        try {
            PrivateKey privateKey = KeyReader.getPrivateKey(DefaultKey.nGetPrivateKey());
            PublicKey publicKey = KeyReader.getPublicKey(DefaultKey.nGetPublicKey());
            return new RSACipher(privateKey, publicKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public RSACipher(@NotNull PrivateKey privateKey, @NotNull PublicKey publicKey) {
        mPrivateKey = privateKey;
        mPublicKey = publicKey;
    }


    public String encrypt(String data) throws GeneralSecurityException {
        if (mPublicKey == null) {
            throw new GeneralSecurityException("encrypt need to publicKey != null");
        }
        if (TextUtils.isEmpty(data)) return null;
        Cipher cipher = Cipher.getInstance(RSA_MODEL);
        cipher.init(Cipher.ENCRYPT_MODE, mPublicKey);
        return HexTools.encodeToBase64(cipher.doFinal(data.getBytes()));
    }

    public String decrypt(String data) throws GeneralSecurityException {
        if (mPrivateKey == null) {
            throw new GeneralSecurityException("encrypt need to privateKey != null");
        }
        if (TextUtils.isEmpty(data)) return null;
        Cipher cipher = Cipher.getInstance(RSA_MODEL);
        cipher.init(Cipher.DECRYPT_MODE, mPrivateKey);
        byte[] source = HexTools.decodeFromBase64(data);
        return new String(cipher.doFinal(source));
    }


    public boolean verifyRSA(String src, String encrypt) throws GeneralSecurityException {

        String decrypt = decrypt(encrypt);
        if (decrypt != null) {
            return decrypt.equals(src);
        }
        return false;
    }


    public boolean verifySignature(String text, String signBase64) throws GeneralSecurityException {
        if (mPublicKey == null) {
            throw new GeneralSecurityException("verifySignature need to publicKey != null");
        }
        Signature signature = Signature.getInstance("NONEwithRSA");
        signature.initVerify(mPublicKey);
        signature.update(text.getBytes());
        boolean ret = signature.verify(HexTools.decodeFromBase64(signBase64));
        SecurityLog.d(TAG, "verifySignature:" + ret);
        return ret;
    }


    public String getSignatureBase64(String text) throws GeneralSecurityException {
        if (mPrivateKey == null) {
            throw new GeneralSecurityException("getSignature need to privateKey != null");
        }

        Signature signature = Signature.getInstance("NONEwithRSA");
        signature.initSign(mPrivateKey);
        signature.update(text.getBytes());
        String sign = HexTools.encodeToBase64(signature.sign());
        SecurityLog.d(TAG, "getSignature: sign=" + sign);
        return sign;

    }
}
